/**
 * 自定义工具DSL系统
 * 不依赖于zod和特定传输协议，提供类型安全的工具定义和验证
 */

// 基础数据类型
export type SchemaType = 'string' | 'number' | 'boolean' | 'array' | 'object' | 'null' | 'any';

// 字段定义
export interface FieldSchema {
  type: SchemaType;
  description?: string;
  required?: boolean;
  default?: any;
  items?: FieldSchema; // 对于数组类型
  properties?: Record<string, FieldSchema>; // 对于对象类型
  enum?: any[]; // 枚举值
  minLength?: number;
  maxLength?: number;
  min?: number; // 向后兼容
  max?: number; // 向后兼容
  minimum?: number; // JSON Schema 标准
  maximum?: number; // JSON Schema 标准
  pattern?: string; // 正则表达式
  format?: string; // JSON Schema 格式
}

// 工具元数据定义
export interface ToolMeta {
  name: string;
  title: string;
  description: string;
  version?: string;
  author?: string;
  tags?: string[];
  category?: string;
  parameters: Record<string, FieldSchema>;
}

// 工具执行结果
export interface ToolResult {
  success: boolean;
  data?: any;
  error?: string;
  message?: string;
}

// 工具函数签名
export type ToolFunction = (params: Record<string, any>) => Promise<ToolResult>;

// 完整工具定义
export interface ToolDefinition {
  meta: ToolMeta;
  handler: ToolFunction;
}

// 验证错误
export class ValidationError extends Error {
  constructor(
    public field: string,
    public value: any,
    public expectedType: SchemaType,
    message?: string
  ) {
    super(
      message ||
        `Validation failed for field '${field}': expected ${expectedType}, got ${typeof value}`
    );
    this.name = 'ValidationError';
  }
}

// 参数验证器
export class ParameterValidator {
  static validate(params: Record<string, any>, schema: Record<string, FieldSchema>): void {
    // 检查必需参数
    for (const [fieldName, fieldSchema] of Object.entries(schema)) {
      if (fieldSchema.required && !(fieldName in params)) {
        throw new ValidationError(
          fieldName,
          undefined,
          fieldSchema.type,
          `Required field '${fieldName}' is missing`
        );
      }
    }

    // 验证每个参数
    for (const [fieldName, value] of Object.entries(params)) {
      const fieldSchema = schema[fieldName];
      if (!fieldSchema) {
        continue; // 允许额外参数
      }

      this.validateField(fieldName, value, fieldSchema);
    }
  }

  private static validateField(fieldName: string, value: any, schema: FieldSchema): void {
    // 检查null值
    if (value === null || value === undefined) {
      if (schema.required) {
        throw new ValidationError(
          fieldName,
          value,
          schema.type,
          `Field '${fieldName}' is required`
        );
      }
      return;
    }

    // 类型检查
    switch (schema.type) {
      case 'string':
        if (typeof value !== 'string') {
          throw new ValidationError(fieldName, value, 'string');
        }
        if (schema.minLength && value.length < schema.minLength) {
          throw new ValidationError(
            fieldName,
            value,
            'string',
            `String too short (min: ${schema.minLength})`
          );
        }
        if (schema.maxLength && value.length > schema.maxLength) {
          throw new ValidationError(
            fieldName,
            value,
            'string',
            `String too long (max: ${schema.maxLength})`
          );
        }
        if (schema.pattern && !new RegExp(schema.pattern).test(value)) {
          throw new ValidationError(
            fieldName,
            value,
            'string',
            `String doesn't match pattern: ${schema.pattern}`
          );
        }
        break;

      case 'number':
        if (typeof value !== 'number' || isNaN(value)) {
          throw new ValidationError(fieldName, value, 'number');
        }
        const minValue = schema.minimum ?? schema.min;
        const maxValue = schema.maximum ?? schema.max;
        if (minValue !== undefined && value < minValue) {
          throw new ValidationError(
            fieldName,
            value,
            'number',
            `Number too small (min: ${minValue})`
          );
        }
        if (maxValue !== undefined && value > maxValue) {
          throw new ValidationError(
            fieldName,
            value,
            'number',
            `Number too large (max: ${maxValue})`
          );
        }
        break;

      case 'boolean':
        if (typeof value !== 'boolean') {
          throw new ValidationError(fieldName, value, 'boolean');
        }
        break;

      case 'array':
        if (!Array.isArray(value)) {
          throw new ValidationError(fieldName, value, 'array');
        }
        if (schema.items) {
          value.forEach((item, index) => {
            this.validateField(`${fieldName}[${index}]`, item, schema.items!);
          });
        }
        break;

      case 'object':
        if (typeof value !== 'object' || Array.isArray(value)) {
          throw new ValidationError(fieldName, value, 'object');
        }
        if (schema.properties) {
          for (const [propName, propSchema] of Object.entries(schema.properties)) {
            this.validateField(`${fieldName}.${propName}`, value[propName], propSchema);
          }
        }
        break;

      case 'any':
        // 任何类型都接受
        break;

      default:
        break;
    }

    // 枚举值检查
    if (schema.enum && !schema.enum.includes(value)) {
      throw new ValidationError(
        fieldName,
        value,
        schema.type,
        `Value must be one of: ${schema.enum.join(', ')}`
      );
    }
  }
}

// DSL构建器，提供更友好的API
export class ToolBuilder {
  private meta: Partial<ToolMeta> = {};
  private parameters: Record<string, FieldSchema> = {};

  name(name: string): this {
    this.meta.name = name;
    return this;
  }

  title(title: string): this {
    this.meta.title = title;
    return this;
  }

  description(description: string): this {
    this.meta.description = description;
    return this;
  }

  version(version: string): this {
    this.meta.version = version;
    return this;
  }

  author(author: string): this {
    this.meta.author = author;
    return this;
  }

  tags(tags: string[]): this {
    this.meta.tags = tags;
    return this;
  }

  category(category: string): this {
    this.meta.category = category;
    return this;
  }

  parameter(name: string, schema: FieldSchema): this {
    this.parameters[name] = schema;
    return this;
  }

  build(handler: ToolFunction): ToolDefinition {
    if (!this.meta.name || !this.meta.title || !this.meta.description) {
      throw new Error('Tool must have name, title, and description');
    }

    const meta: ToolMeta = {
      name: this.meta.name,
      title: this.meta.title,
      description: this.meta.description,
      version: this.meta.version,
      author: this.meta.author,
      tags: this.meta.tags,
      category: this.meta.category,
      parameters: this.parameters,
    };

    // 包装处理器以添加参数验证
    const wrappedHandler: ToolFunction = async (
      params: Record<string, any>
    ): Promise<ToolResult> => {
      try {
        ParameterValidator.validate(params, this.parameters);
        return await handler(params);
      } catch (error) {
        if (error instanceof ValidationError) {
          return {
            success: false,
            error: error.message,
          };
        }
        throw error;
      }
    };

    return {
      meta,
      handler: wrappedHandler,
    };
  }
}

// ==== 兼容性类型定义 ====
// 为了兼容现有代码中使用的简化版本类型定义

// DSL Schema 类型（简化版本，向后兼容）
export interface DslSchema {
  properties?: Record<string, FieldSchema>;
  required?: string[];
  additionalProperties?: boolean;
}

// 简化的工具接口（向后兼容）
export interface Tool {
  name: string;
  description: string;
  schema?: DslSchema;
  execute: (params: any) => Promise<any>;
}

// 便捷函数 - 支持两种使用方式

// 使用配置对象直接创建工具
interface ToolConfig {
  name: string;
  title?: string;
  description: string;
  version?: string;
  author?: string;
  tags?: string[];
  category?: string;
  parameters?: Record<string, FieldSchema>;
  handler: ToolFunction;
}

export function createTool(config: ToolConfig): ToolDefinition;
export function createTool(): ToolBuilder;
export function createTool(config?: ToolConfig): ToolDefinition | ToolBuilder {
  if (config) {
    // 直接从配置对象创建工具
    const meta: ToolMeta = {
      name: config.name,
      title: config.title || config.name,
      description: config.description,
      version: config.version,
      author: config.author,
      tags: config.tags,
      category: config.category,
      parameters: config.parameters || {},
    };

    // 包装处理器以添加参数验证
    const wrappedHandler: ToolFunction = async (
      params: Record<string, any>
    ): Promise<ToolResult> => {
      try {
        if (config.parameters) {
          ParameterValidator.validate(params, config.parameters);
        }
        return await config.handler(params);
      } catch (error) {
        if (error instanceof ValidationError) {
          return {
            success: false,
            error: error.message,
          };
        }
        throw error;
      }
    };

    return {
      meta,
      handler: wrappedHandler,
    };
  } else {
    // 返回 builder pattern
    return new ToolBuilder();
  }
}

// 字段构建器
export const field = {
  string: (options?: Partial<FieldSchema>): FieldSchema => ({
    type: 'string',
    ...options,
  }),

  number: (options?: Partial<FieldSchema>): FieldSchema => ({
    type: 'number',
    ...options,
  }),

  boolean: (options?: Partial<FieldSchema>): FieldSchema => ({
    type: 'boolean',
    ...options,
  }),

  array: (items: FieldSchema, options?: Partial<FieldSchema>): FieldSchema => ({
    type: 'array',
    items,
    ...options,
  }),

  object: (
    properties: Record<string, FieldSchema>,
    options?: Partial<FieldSchema>
  ): FieldSchema => ({
    type: 'object',
    properties,
    ...options,
  }),

  optional: (schema: FieldSchema): FieldSchema => ({
    ...schema,
    required: false,
  }),

  required: (schema: FieldSchema): FieldSchema => ({
    ...schema,
    required: true,
  }),
};
